package com.eden.api.security.service;


import com.eden.common.constant.ApiConstants;
import com.eden.api.security.LoginUser;
import com.eden.api.security.annotation.PermissionsRequired;
import com.eden.api.security.annotation.RolesRequired;
import com.eden.api.security.enums.RequiredMode;
import com.eden.common.utils.ServletUtils;
import com.eden.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 自定义鉴权实现
 * 
 * @author wenqing
 */
@Service("authorizationService")
public class AuthorizationService {

    @Autowired
    private ITokenService tokenService;

    /**
     * 验证用户是否具备某些权限
     *
     * @param permissionsRequired 所需权限注解
     * @return 用户是否具备某些权限
     */
    public boolean hasPermissions(PermissionsRequired permissionsRequired) {
        return hasPermissions(permissionsRequired.requiredMode(), permissionsRequired.value());
    }

    /**
     * 验证用户是否具备某些权限
     *
     * @param requiredMode
     * @param permissions 权限数组
     * @return 用户是否具备某些权限
     */
    public boolean hasPermissions(RequiredMode requiredMode, String...permissions) {
        if (RequiredMode.NONE.equals(requiredMode) || permissions.length == 0) {
            return true;
        }
        boolean hasPermissions = true;
        if (permissions.length == 1) {
            hasPermissions = hasPermissions(permissions[0]);
        } else if (RequiredMode.AND.equals(requiredMode)) {
            hasPermissions = hasPermissions(permissions);
        } else {
            if(RequiredMode.OR.equals(requiredMode)) {
                boolean hasAtLeastOnePermission = false;
                for (String permission : permissions) {
                    if(hasPermissions(permission)) {
                        hasAtLeastOnePermission = true;
                        break;
                    }
                }
                hasPermissions = hasAtLeastOnePermission;
            }
        }
        return hasPermissions;
    }

    /**
     * 验证用户是否具备某权限
     *
     * @param permissions 权限数组
     * @return 用户是否具备某些权限
     */
    public boolean hasPermissions(String...permissions) {
        if(permissions.length == 0){
            return true;
        }
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        if (StringUtils.isNull(loginUser) || StringUtils.isEmpty(loginUser.getPermissions())) {
            return false;
        }
        Set<String> userPermissions = loginUser.getPermissions();
        Set<String> requiresPermissions = new HashSet<>(Arrays.asList(permissions));
        return userPermissions.contains(ApiConstants.ALL_PERMISSION_KEY) || userPermissions.containsAll(requiresPermissions);
    }

    /**
     * 验证用户是否具备某些角色
     *
     * @param rolesRequired 所需角色注解
     * @return 用户是否具备某些角色
     */
    public boolean hasRoles(RolesRequired rolesRequired) {
        return hasRoles(rolesRequired.requiredMode(), rolesRequired.value());
    }

    /**
     * 验证用户是否具备某些角色
     *
     * @param requiredMode
     * @param roles 角色数组
     * @return 用户是否具备某些角色
     */
    public boolean hasRoles(RequiredMode requiredMode, String...roles) {
        if (RequiredMode.NONE.equals(requiredMode) || roles.length == 0) {
            return true;
        }
        boolean hasRoles = true;
        if (roles.length == 1) {
            hasRoles = hasPermissions(roles[0]);
        } else if (RequiredMode.AND.equals(requiredMode)) {
            hasRoles = hasPermissions(roles);
        } else {
            if(RequiredMode.OR.equals(requiredMode)) {
                boolean hasAtLeastOneRole = false;
                for (String role : roles) {
                    if(hasRoles(role)) {
                        hasAtLeastOneRole = true;
                        break;
                    }
                }
                hasRoles = hasAtLeastOneRole;
            }
        }
        return hasRoles;
    }

    /**
     * 验证用户是否具备某些角色
     *
     * @param roles 角色数组
     * @return 用户是否具备某些角色
     */
    public boolean hasRoles(String...roles) {
        if(roles.length == 0){
            return true;
        }
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        if (StringUtils.isNull(loginUser) || StringUtils.isEmpty(loginUser.getPermissions())) {
            return false;
        }
        Set<String> userRoles = loginUser.getRoles();
        Set<String> requiresRoles = new HashSet<>(Arrays.asList(roles));
        return userRoles.contains(ApiConstants.SUPER_ROLE_KEY) || userRoles.containsAll(requiresRoles);
    }
}
